//
// Created by Administrator on 2019/9/19.
//

#ifndef LEARNOPENGLPRO_SHADER_H
#define LEARNOPENGLPRO_SHADER_H

#include <GLES2/gl2.h>
#include <string>
#include <map>
#include "GLTexture.h"

enum ShaderType {
    PROGRAM,
    VERTEX,
    FRAGMENT
};

typedef std::map<std::string, int> handleMapType;

class Shader {
public:
    /**
     * openGL程序id
     */
    unsigned int programID;
    handleMapType handleMap;

public:

    Shader(const char *vertexSource, const char *fragmentSource);

    ~Shader();

    /**
     * 使用着色器程序
     */
    void use() const;

    /**
     * 获取着色器属性操作句柄
     * @param name
     * @param errorNotExist
     * @return
     */
    int getHandle(const std::string &name, bool errorNotExist = true);

    void setBool(const std::string &name, bool value);

    void setInt(const std::string &name, int value);

    void setFloat(const std::string &name, float value);

    void setUniform1i(const std::string &name, GLint x);

    void setUniform2i(const std::string &name, GLint x, GLint y);

    void setUniform1iv(const std::string &name, int count, GLint *p);

    void setUniform1f(const std::string &name, GLfloat x);

    void setUniform2f(const std::string &name, GLfloat x, GLfloat y);

    void setUniform3f(const std::string &name, GLfloat x, GLfloat y, GLfloat z);

    void setUniform4f(const std::string &name, GLfloat x, GLfloat y, GLfloat z, GLfloat w);

    void setUniform1fv(const std::string &name, int count, GLfloat *p);

    void setUniform2fv(const std::string &name, int count, GLfloat *p);

    void setUniform4fv(const std::string &name, int count, GLfloat *p);

    void setUniformMatrix4fv(const std::string &name, GLsizei count, GLboolean transpose, const GLfloat *value);

    void setUniformMatrix3fv(const std::string &name, GLsizei count, GLboolean transpose, const GLfloat *value);

    void setVertexAttribPointer(const std::string &name, GLint size, GLenum type, GLboolean normalized, GLsizei stride,
                                void *ptr);

    void setVertexAttrib(const std::string &name, GLint size, GLenum type, GLboolean normalized, GLsizei stride, int offset);

    void setVertexAttribPointer(GLint location, GLint size, GLenum type, GLboolean normalized, GLsizei stride,
                                void *ptr);

    void setVertexAttrib(GLint location, GLint size, GLenum type, GLboolean normalized, GLsizei stride, int offset);

    void disableVertexAttrib(const std::string &name);

    void setUniformTexture(const std::string &name, GLint x, GLuint textureID, GLenum target = GL_TEXTURE_2D);

    int getUniformCount();

    GLTexture* loadGLTexture(void *data,int width, int height);

    void setTexture(const std::string &name, GLint x, GLTexture *texture);

private:
    bool compileShader(GLuint *shader, GLenum type, const char *source);

    bool checkCompileErrors(GLuint shader, ShaderType type);

    void checkGLError(const char *op);
};


#endif //LEARNOPENGLPRO_SHADER_H
